package com.zone.domain.award.service.distribute.impl;

import com.google.common.collect.Range;
import com.zone.domain.award.model.aggregate.UserCreditAggregate;
import com.zone.domain.award.model.entity.AwardEntity;
import com.zone.domain.award.model.entity.DistributeAwardEntity;
import com.zone.domain.award.model.entity.UserAwardRecordEntity;
import com.zone.domain.award.model.entity.UserCreditAccountEntity;
import com.zone.domain.award.model.valobj.AwardStateEnum;
import com.zone.domain.award.model.valobj.UserCreditAccountStatus;
import com.zone.domain.award.repository.IAwardRepository;
import com.zone.domain.award.service.distribute.IDistributeAwardService;
import com.zone.domain.common.factory.FactoryName;
import com.zone.types.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author: zongzi
 * @description: 用户积分发奖处理器
 * @date: 2025/3/9
 */
@Component("user_credit_random")
public class UserCreditHandler implements IDistributeAwardService, FactoryName {
    @Autowired
    private IAwardRepository awardRepository;

    @Override
    public void executeHandOutPrizes(DistributeAwardEntity distributeAward) {
        // 获取积分配置值（如果是黑名单积分则透传到处理器中）,反之则直接查询数据库信息
        String creditConfigStr = distributeAward.getAwardConfig();
        if (Strings.isBlank(creditConfigStr)) {
            AwardEntity award = awardRepository.queryAward(distributeAward.getAwardId());
            Validate.notNull(award, "未查询到award, id = %s", distributeAward.getAwardId());
            creditConfigStr = award.getAwardConfig();
        }
        Range<BigDecimal> creditRange = this.parseBlackValue(creditConfigStr);
        Validate.notNull(creditRange, "award 解析积分配置失败, creditConfigStr = %s", creditConfigStr);
        // 获取范围内的随机值
        BigDecimal random = this.getRandom(creditRange);
        // 构造聚合对象
        UserCreditAggregate userCreditAggregate = new UserCreditAggregate();
        // 用户积分账户
        UserCreditAccountEntity userCreditAccountEntity = new UserCreditAccountEntity();
        userCreditAccountEntity.setUserId(distributeAward.getUserId());
        userCreditAccountEntity.setTotalAmount(random);
        userCreditAccountEntity.setAvailableAmount(random);
        userCreditAccountEntity.setAccountStatus(UserCreditAccountStatus.OPEN);
        userCreditAggregate.setUserCreditAccount(userCreditAccountEntity);
        // 用户中奖记录
        UserAwardRecordEntity userAwardRecordEntity = new UserAwardRecordEntity();
        userAwardRecordEntity.setUserId(distributeAward.getUserId());
        userAwardRecordEntity.setActivityId(distributeAward.getActivityId());
        userAwardRecordEntity.setOrderId(distributeAward.getOrderId());
        userAwardRecordEntity.setAwardId(distributeAward.getAwardId());
        userAwardRecordEntity.setAwardState(AwardStateEnum.COMPLETED);
        userCreditAggregate.setUserAwardRecord(userAwardRecordEntity);
        // 积分账户落库
        awardRepository.saveUserCreditAccount(userCreditAggregate);
    }

    @Override
    public String getName() {
        return "user_credit_random";
    }

    // 解析黑名单配置数据(1,100)，返回范围【1,100】
    private Range<BigDecimal> parseBlackValue(String creditConfigStr) {
        if (Strings.isBlank(creditConfigStr)) {
            return null;
        }
        String start = StringUtils.substringBefore(creditConfigStr, ",");
        String end = StringUtils.substringAfter(creditConfigStr, ",");
        try {
            return Range.closed(new BigDecimal(start), new BigDecimal(end));
        } catch (Exception e) {
            String errorMsg = String.format("award.award_config 转换黑名单数据失败, 请检查配置 value = %s", creditConfigStr);
            throw new BizException(errorMsg);
        }
    }

    /**
     * 获取指定范围中的随机值
     *
     * @return
     */
    public BigDecimal getRandom(Range<BigDecimal> creditRange) {
        BigDecimal lowerEndpoint = creditRange.lowerEndpoint();
        BigDecimal upperEndpoint = creditRange.upperEndpoint();
        float minF = lowerEndpoint.floatValue();
        float maxF = upperEndpoint.floatValue();
        //生成随机数
        BigDecimal db = new BigDecimal(Math.random() * (maxF - minF) + minF);
        //返回保留两位小数的随机数。不进行四舍五入
        return db.setScale(2, RoundingMode.DOWN);
    }
}
